<?php
namespace lib\JhWechat;

/**
 * 服务器通信
 * @Auth: JH <hu@lunaz.cn>
 * Class Server
 * @package lib\JhWechat
 */
class Server extends Base
{
    private $appId;
    private $appSecret;
    private $token;
    private $encodingAesKey;
    private $typeEncrypt;
    protected $msgData;

    /**
     * @param array $options
     * @param string $access_token
     */
    function __construct(array $options = array(), $access_token = '')
    {
        if ($access_token) {
            parent::$accessToken = $access_token;
        }
        if ($options) {
            parent::$config = $options;
        }
        $this->token = isset(parent::$config['token']) ? parent::$config['token'] : '';
        $this->encodingAesKey = isset(parent::$config['encodingAesKey']) ? parent::$config['encodingAesKey'] : '';
        $this->appId = isset(parent::$config['appId']) ? parent::$config['appId'] : '';
        $this->appSecret = isset(parent::$config['appSecret']) ? parent::$config['appSecret'] : '';
        $this->typeEncrypt = isset($_GET['encrypt_type']) ? $_GET['encrypt_type'] : '';
        parent::__construct();
    }

    function setData(array $data)
    {
        $this->msgData = $data;
    }

    /**
     * @param $data
     *
     * @return array
     */
    function parseData(&$data)
    {
        $data = $this->parseXML($data);
        // 如果公众号使用加密模式
        if (isset($data['Encrypt']) && $this->typeEncrypt == 'aes') {
            $data = $this->parseXML((new Crypt(parent::$config))->deCrypt($data['Encrypt']));
        }
        $this->msgData = $data;
    }

    /**
     * signature
     *
     * @param array $tmp
     * @return string
     */
    private function signature(array $tmp)
    {
        sort($tmp, SORT_STRING);
        return sha1(implode('', $tmp));
    }

    /**
     * @param array $params
     *
     * @return bool
     */
    function check(array $params)
    {
        if (!isset($params['signature'])) {
            return false;
        }
        $timestamp = isset($params['timestamp']) ? $params['timestamp'] : '';
        $nonce = isset($params['nonce']) ? $params['nonce'] : '';
        return ($params['signature'] == $this->signature([$this->token, $timestamp, $nonce]));
    }

    function getMPid()
    {
        if (empty($this->msgData['ToUserName'])) {
            throw new Exception('无效的微信公众号ID');
        }
        return $this->msgData['ToUserName'];
    }

    function getOpenId()
    {
        if (empty($this->msgData['FromUserName'])) {
            throw new Exception('无效的接收微信帐号ID');
        }
        return $this->msgData['FromUserName'];
    }

    private function getBaseData($type)
    {
        return array(
            'ToUserName' => $this->getOpenId(),
            'FromUserName' => $this->getMPid(),
            'CreateTime' => time(),
            'MsgType' => $type
        );
    }

    /**
     * 回复文本信息
     *
     * @param string $content
     */
    function responseText($content = 'ok')
    {
        $base = $this->getBaseData('text');
        $base['Content'] = $content;
        $this->push($this->makeXML($base));
    }

    /**
     * 将接收到的信息转发给客服，前提必须有客服在线
     * 可用有KfManager 类查询是否有客服在线
     *
     * @param string $to_KfAccount 转发到指定客服账号
     */
    function transferKf($to_KfAccount = '')
    {
        $base = $this->getBaseData('transfer_customer_service');
        if ($to_KfAccount) {
            $base += array(
                'TransInfo' => array('KfAccount' => $to_KfAccount)
            );
        }
        $this->push($this->makeXML($base));
    }

    /**
     * @param $data
     * @throws Exception
     */
    function push($data)
    {
        if ($this->typeEncrypt == 'aes') {
            $crypt = new Crypt(parent::$config);
            $enCrypt = $crypt->enCrypt($data);
            $nonce = $crypt->randStr();
            $sign = $this->signature(array($this->token, $_SERVER['REQUEST_TIME'], $nonce, $enCrypt));
            $data = $this->makeXML(array(
                'Encrypt' => $enCrypt,
                'MsgSignature' => $sign,
                'TimeStamp' => $_SERVER['REQUEST_TIME'],
                'Nonce' => $nonce
            ));
        }
        echo $data;
    }

    /**
     * 普通消息类型转换为控制器类名称
     *
     * @param $msgType
     * @return mixed|string
     */
    function msgTypeToController($msgType)
    {
        //http://mp.weixin.qq.com/wiki/17/fc9a27730e07b9126144d9c96eaf51f9.html
        $msgTypeConfig = array('shortvideo' => 'ShortVideo');
        if (isset($msgTypeConfig[$msgType])) {
            return $msgTypeConfig[$msgType];
        }

        return ucfirst($msgType);
    }

    /**
     * 事件转换为控制器方法
     *
     * @param string $event
     * @return mixed|string
     */
    function eventToAction($event)
    {
        //http://mp.weixin.qq.com/wiki/14/f79bdec63116f376113937e173652ba2.html
        $eventConfig = array(
            'subscribe' => 'subscribe', 'unsubscribe' => 'unSubscribe',
            'SCAN' => 'scan', 'LOCATION' => 'location', 'CLICK' => 'click', 'VIEW' => 'view'
        );

        if (isset($eventConfig[$event])) {
            return $eventConfig[$event];
        } else {
            return 'index';
        }
    }

}
